package com.ywu.standard.menu.service;

import com.ywu.boot.context.YwuContext;
import com.ywu.boot.context.YwuContextHolder;
import com.ywu.boot.context.YwuContextRole;
import com.ywu.boot.context.YwuContextUser;
import com.ywu.boot.utils.RedisUtils;
import com.ywu.common.entity.PageList;
import com.ywu.common.gson.GsonUtils;
import com.ywu.common.page.PageService;
import com.ywu.common.result.CommonResult;
import com.ywu.component.spi.entity.ComponentEntity;
import com.ywu.component.spi.spi.ComponentSpi;
import com.ywu.standard.menu.constant.MenuConstant;
import com.ywu.standard.menu.data.MenuRepository;
import com.ywu.standard.menu.data.RouterPathRepository;
import com.ywu.standard.menu.dto.RouterPathDto;
import com.ywu.standard.menu.entity.MenuEntity;
import com.ywu.standard.menu.entity.RouterPathEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @ClassName RouterPathService
 * @Description TODO
 * @Author GroundDemo
 * @Date 2024/3/30 19:38
 * @Version 1.0
 **/
@Service
@Slf4j
public class RouterPathService {
    @Autowired
    private RouterPathRepository repository;

    @Autowired
    private MenuRepository menuRepository;

    @Autowired
    private ComponentSpi componentSpi;

    // 站点缓存key
    private static final String ROUTE_SITE_REDIS_KEY = "YWU_ROUTE_SITE:site";

    /**
    * @Author GroundDemo
    * @Description 添加文根
    * @Date 19:51 2024/3/30
    * @Param [routerPathDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> createRouteRootPath(RouterPathDto routerPathDto) {
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        // 校验文根是否存在
        RouterPathDto searchDto = new RouterPathDto();
        searchDto.setRouteRootPath(routerPathDto.getRouteRootPath());
        searchDto.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        RouterPathEntity checkRoutePathEntities = repository.checkRouteRootPathEntity(searchDto);
        if (Objects.nonNull(checkRoutePathEntities)) {
            return CommonResult.error().setCode(MenuConstant.ROUTE_ROOT_PATH_EXIST_ERROR.getCode())
                    .setErrorCode(MenuConstant.ROUTE_ROOT_PATH_EXIST_ERROR.getErrorCode())
                    .setMessage(MenuConstant.ROUTE_ROOT_PATH_EXIST_ERROR.getMessage());
        }
        // 构建entity对象
        RouterPathEntity routerPathEntity = new RouterPathEntity();
        BeanUtils.copyProperties(routerPathDto, routerPathEntity);
        routerPathEntity.createInfo(currentContext.getYwuContextUser().getUserAccount());
        routerPathEntity.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        repository.createRoutePathInfo(routerPathEntity);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 更新文根
    * @Date 19:54 2024/3/30
    * @Param [routerPathDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> updateRouteRootPath(RouterPathDto routerPathDto) {
        // 校验文根是否存在
        RouterPathDto searchDto = new RouterPathDto();
        String routeRootPath = routerPathDto.getRouteRootPath();
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        searchDto.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        searchDto.setId(routerPathDto.getId());
        searchDto.setRouteRootPath(routeRootPath);
        RouterPathEntity checkRoutePathEntities = repository.checkRouteRootPathEntity(searchDto);
        if (Objects.isNull(checkRoutePathEntities) || Objects.isNull(checkRoutePathEntities.getId())) {
            return CommonResult.error().setCode(MenuConstant.ROUTE_ROOT_PATH_NOT_EXIST_ERROR.getCode())
                    .setErrorCode(MenuConstant.ROUTE_ROOT_PATH_NOT_EXIST_ERROR.getErrorCode())
                    .setMessage(MenuConstant.ROUTE_ROOT_PATH_NOT_EXIST_ERROR.getMessage());
        }
        // 更新文根
        RouterPathEntity routerPathEntity = new RouterPathEntity();
        BeanUtils.copyProperties(routerPathDto, routerPathEntity);
        routerPathEntity.updateInfo(currentContext.getYwuContextUser().getUserAccount());
        repository.updateRoutePathInfo(routerPathEntity);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 删除文根
    * @Date 19:55 2024/3/30
    * @Param [routerPathDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> deleteRouteRootPath(RouterPathDto routerPathDto) {
        RouterPathEntity routerPathEntity = new RouterPathEntity();
        BeanUtils.copyProperties(routerPathDto, routerPathEntity);
        repository.deleteRoutePathInfo(routerPathEntity);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 查询文根列表
    * @Date 19:56 2024/3/30
    * @Param [routerPathDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> queryRouteRootPath(RouterPathDto routerPathDto) {
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        routerPathDto.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        // 查询数量
        int count = repository.queryRoutePathCount(routerPathDto);
        PageService.execPageStartAndEnd(routerPathDto.getPageInfo());
        List<RouterPathEntity> routerPathEntities = repository.queryRoutePathInfo(routerPathDto);
        List<Integer> componentIds = routerPathEntities.stream().map(RouterPathEntity::getComponentId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(componentIds)) {
            // 查询关联的组件信息
            CommonResult<List<ComponentEntity>> componentQueryRes = componentSpi.batchQueryByIdsWithNoContent(componentIds);
            if (!componentQueryRes.getCode().equals("200")) {
                return CommonResult.error().setErrorCode("component.query.error").setMessage("组件查询失败");
            }
            List<ComponentEntity> data = componentQueryRes.getData();
            Map<Integer, ComponentEntity> componentMap = data.stream().collect(Collectors.toMap(ComponentEntity::getId, res -> res, (v1, v2) -> v1));
            routerPathEntities.forEach(res -> {
                if (componentMap.containsKey(res.getComponentId())) {
                    ComponentEntity componentEntity = componentMap.get(res.getComponentId());
                    res.setComponentName(componentEntity.getComponentName());
                    res.setComponentCnName(componentEntity.getComponentCnName());
                }
            });
        }
        // 构建pageList对象
        PageList<RouterPathEntity> routerPathEntityPageList = new PageList<>(routerPathDto.getPageInfo().getPageIndex(),
                routerPathDto.getPageInfo().getPageSize(), count, routerPathEntities);
        return CommonResult.success(routerPathEntityPageList);
    }

    /**
    * @Author GroundDemo
    * @Description 查询当前用户可以进入的路由文根（站点）
    * @Date 18:02 2024/8/25
    * @Param []
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> queryRouteSite() {
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        YwuContextUser ywuContextUser = currentContext.getYwuContextUser();
        // 先查询缓存中的数据
        String redisInfo = RedisUtils.getHashByKey(ROUTE_SITE_REDIS_KEY, String.valueOf(ywuContextUser.getId()));
        if (Objects.nonNull(redisInfo)) {
            log.debug("using redis cache");
            // 缓存命中，解析缓存数据
            List<RouterPathEntity> redisSiteInfo = GsonUtils.deserializeList(redisInfo, RouterPathEntity.class);
            return CommonResult.success(redisSiteInfo);
        }
        // 缓存不存在，则查询数据库
        List<YwuContextRole> ywuContestRole = currentContext.getYwuContestRole();
        // 用户角色信息是从网关填入的，这里可以直接获取
        Set<String> userRoleCodes = ywuContestRole.stream().map(YwuContextRole::getRoleCode).collect(Collectors.toSet());
        List<MenuEntity> menuEntityList = menuRepository.queryMenuByCurrentPermission(userRoleCodes);
        // 根据当前查询出的菜单挂载的站点，查询站点信息（对站点进行去重）
        Set<Integer> routeIds = menuEntityList.stream().map(MenuEntity::getRouteRootId).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(routeIds)) {
            return CommonResult.success(new ArrayList<>());
        }
        // 根据文根ID查询路由文根
        List<RouterPathEntity> routerPathEntityList = repository.queryRoutePathInfoByIds(new ArrayList<>(routeIds), "1");
        // 将当前查询出的路由文根信息存入缓存，key为当前用户ID
        String serialize = GsonUtils.serialize(routerPathEntityList);
        RedisUtils.hashSet(ROUTE_SITE_REDIS_KEY, String.valueOf(ywuContextUser.getId()), serialize);
        RedisUtils.setExpire(ROUTE_SITE_REDIS_KEY, 1, TimeUnit.HOURS);
        return CommonResult.success(routerPathEntityList);
    }
}
